class SET{
    constructor() {
        this.items = {} //存储集合内的基本数据结构
    }
    has(ele){ //判断是否存在元素
        return Object.prototype.hasOwnProperty.call(this.items,ele) //集合只存储元素
    }
    add(ele){
        //往里面添加元素前应该先判断是否存在元素
        if(!this.has(ele)){ //如果不存在这么一个值，则添加，否则不能添加
            this.items[ele] = ele //直接用元素的内容做索引
            return true //表示添加成功
        }
        return false //表示添加失败
    }
    delete(ele){ //删除一个值
        if(this.has(ele)){ //当这个元素存在的时候才能删，否则不能删除
            delete this.items[ele]
            return true //删除成功
        }
        return false //删除失败
    }
    clear(){ //清空集合
        this.items = {}
    }
    size(){
        return Object.keys(this.items).length
    }
    values(){ //获得集合内所有的值
        return Object.values(this.items)
    }
    union(otherSet){ //并集
        let unionSet = new SET() //用一个新的集合来保存两个集合的内容
        this.values().forEach(value=>unionSet.add(value)) //将本地实例的集合的值添加到新创建的集合中
        otherSet.values().forEach(value=>unionSet.add(value)) //将其他实例的集合的值添加到新创建的集合中
        return unionSet
    }
    intersection(otherSet){ //交集
        //必须在A里面又在B里面
        let intersectionSet = new SET() //同样先新建一个集合来保存

        //先把两个集合中的值各自取出来比较谁更少一点，可以用少的来比较，更快更能节省性能，因为必须在少的里面也有才算交集
        let values = this.values() //取出当前实例的集合的值保存在变量values中
        let otherValues = otherSet.values() //取出其他实例的集合的值保存在变量otherValues中

        //创建两个变量，大的和小的
        let bigger,smaller
        //不要牺牲可读性来实现代码的精简，比如下面的判断可以用三目，但会影响后期的可读性与可维护性，不容易让人理解
        if(values.length > otherValues.length){ //当本地实例的集合的值多于其他实例的集合的值时，小的等于数组，大的等于set集合
            bigger = this //大的等于集合，因为forEach遍历里面大的要使用集合的has方法来判断是否拥有相同值
            smaller = otherValues //小的等于数组，因为下面的forEach遍历是用小的
        }else{
            bigger = otherSet //大的等于集合
            smaller = values //小的等于数组
        }

        //然后用小的来遍历每一个值与大的作比较
        smaller.forEach(value=>{
            if(bigger.has(value)){
                intersectionSet.add(value) //如果大的中也存在这个值，则添加进去
            }
        })
        return intersectionSet
    }
    difference(otherSet){ //补集
        let differenceSet = new SET() //创建一个新的补集

        //A的补集必须是B里面没有的
        this.values().forEach(value=>{
            if(!otherSet.has(value)){
                differenceSet.add(value)
            }
        })
    }
    isSubsetOf(otherSet){ //判断A是否是B的子集
        if(this.size() > otherSet.size()){ //如果A的长度大于B的长度，那不可能是子集
            return false
        }
        let isSubset = true //先默认是
        let values = this.values()
        for(let i = 0; i < values.length; i++){
            if(!otherSet.has(values[i])){ //如果B里面没有A里面的值，那么A肯定也不是B的子集，直接改为false并跳出循环
                isSubset = false
                break
            }
        }
        return isSubset
    }
}